package com.yalemang.photovalut.base.helper;

import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.LogUtils;

import java.util.Objects;

/**
 * RecyclerView 网格布局 间隔帮助类
 */
public class CommonItemDecoration extends RecyclerView.ItemDecoration {

    //Item垂直方向间距
    private float dpItemVertical;
    //Item水平方向间距
    private float dpItemHorizontal;

    //注意，只有item固定才有效，动态的改变item个数的，建议使用RecyclerView的padding & margin搞定
    private float left = -1, top = -1, right = -1, bottom = -1;

    private boolean isSetPadding = false;

    private OuterDistanceType type = OuterDistanceType.PADDING;

    public enum OuterDistanceType {
        MARGIN,
        PADDING
    }

    /**
     * @param dp item垂直 & 水平方向间隔
     * @return
     */
    public static RecyclerView.ItemDecoration getItemDecoration(int dp) {
        return builder()
                .setHorizontal(dp)
                .setVertical(dp)
                .build();
    }

    public static Builder builder() {
        return new Builder();
    }

    public float getDpItemVertical() {
        return dpItemVertical;
    }

    public void setDpItemVertical(float dpItemVertical) {
        this.dpItemVertical = dpItemVertical;
    }

    public float getDpItemHorizontal() {
        return dpItemHorizontal;
    }

    public void setDpItemHorizontal(float dpItemHorizontal) {
        this.dpItemHorizontal = dpItemHorizontal;
    }

    public float getLeft() {
        return left;
    }

    public void setLeft(float left) {
        this.left = left;
    }

    public float getTop() {
        return top;
    }

    public void setTop(float top) {
        this.top = top;
    }

    public float getRight() {
        return right;
    }

    public void setRight(float right) {
        this.right = right;
    }

    public float getBottom() {
        return bottom;
    }

    public void setBottom(float bottom) {
        this.bottom = bottom;
    }

    public OuterDistanceType getType() {
        return type;
    }

    public void setType(OuterDistanceType type) {
        this.type = type;
    }

    /**
     * 处理外边距
     */
    private void handlerOuterDistance(RecyclerView parent) {
        if (!isSetPadding) {
            if (type == OuterDistanceType.PADDING) {
                LogUtils.d(this.getClass().getSimpleName(), "Padding Type");
                int adjustLeft;
                if (left >= 0) {
                    adjustLeft = dpToPx(left);
                } else {
                    adjustLeft = parent.getPaddingLeft();
                    if (adjustLeft <= 0) {
                        adjustLeft = parent.getPaddingStart();
                    }
                }
                int adjustTop;
                if (top >= 0) {
                    adjustTop = dpToPx(top);
                } else {
                    adjustTop = parent.getPaddingTop();
                }
                int adjustRight;
                if (right >= 0) {
                    adjustRight = dpToPx(right);
                } else {
                    adjustRight = parent.getPaddingRight();
                    if (adjustRight <= 0) {
                        adjustRight = parent.getPaddingEnd();
                    }
                }
                int adjustBottom;
                if (bottom >= 0) {
                    adjustBottom = dpToPx(bottom);
                } else {
                    adjustBottom = parent.getPaddingBottom();
                }
                parent.setPadding(adjustLeft, adjustTop, adjustRight, adjustBottom);
            } else {
                LogUtils.d(this.getClass().getSimpleName(), "Margin Type");
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
                int adjustLeft;
                if (left >= 0) {
                    adjustLeft = dpToPx(left);
                } else {
                    adjustLeft = layoutParams.leftMargin;
                    if (adjustLeft <= 0) {
                        adjustLeft = layoutParams.getMarginStart();
                    }
                }
                int adjustTop;
                if (top >= 0) {
                    adjustTop = dpToPx(top);
                } else {
                    adjustTop = layoutParams.topMargin;
                }
                int adjustRight;
                if (right >= 0) {
                    adjustRight = dpToPx(right);
                } else {
                    adjustRight = layoutParams.rightMargin;
                    if (adjustLeft <= 0) {
                        adjustRight = layoutParams.getMarginEnd();
                    }
                }
                int adjustBottom;
                if (bottom >= 0) {
                    adjustBottom = dpToPx(bottom);
                } else {
                    adjustBottom = layoutParams.bottomMargin;
                }
                layoutParams.setMargins(adjustLeft, adjustTop, adjustRight, adjustBottom);
                parent.setLayoutParams(layoutParams);
            }
            isSetPadding = true;
        }
    }

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        //handlerOuterDistance(parent);
        if (parent.getLayoutManager() instanceof GridLayoutManager) {
            handleGridLayoutManager(outRect, view, parent, state);
        } else if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            handleLinearLayoutManager(outRect, view, parent, state);
        } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) {
            handleStaggeredGridLayoutManager(outRect, view, parent, state);
        } else {
            throw new RuntimeException("No Match LayoutManager：" + Objects.requireNonNull(parent.getLayoutManager()).getClass().getName());
        }
    }

    private void handleGridLayoutManager(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int itemCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
        int spanCount = 0;
        if (gridLayoutManager != null) {
            spanCount = gridLayoutManager.getSpanCount();
        }
        if (Objects.requireNonNull(gridLayoutManager).getOrientation() == GridLayoutManager.VERTICAL) {
            //横向
            if (position % spanCount == 0) {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
            } else if (position % spanCount == spanCount - 1) {
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            } else {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            }
            //垂直方向
            if (position < spanCount) {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            } else if (position >= itemCount - spanCount) {
                outRect.top = dpToPx(dpItemVertical) / 2;
            } else {
                outRect.top = dpToPx(dpItemVertical) / 2;
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            }
        } else {
            //横向
            if (position % spanCount == 0) {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            } else if (position % spanCount == spanCount - 1) {
                outRect.top = dpToPx(dpItemVertical) / 2;
            } else {
                outRect.right = dpToPx(dpItemVertical) / 2;
                outRect.left = dpToPx(dpItemVertical) / 2;
            }
            //垂直方向
            if (position < spanCount) {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
            } else if (position >= itemCount - spanCount) {
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            } else {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            }
        }
    }

    private void handleLinearLayoutManager(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int itemCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) parent.getLayoutManager();
        if (Objects.requireNonNull(linearLayoutManager).getOrientation() == LinearLayoutManager.HORIZONTAL) {
            if (position == 0) {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
            } else if (position == itemCount - 1) {
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            } else {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            }
        } else {
            if (position == 0) {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            } else if (position == itemCount - 1) {
                outRect.top = dpToPx(dpItemVertical) / 2;
            } else {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
                outRect.top = dpToPx(dpItemVertical) / 2;
            }
        }
    }

    private void handleStaggeredGridLayoutManager(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int itemCount = Objects.requireNonNull(parent.getAdapter()).getItemCount();
        StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager();
        int spanCount = 0;
        if (staggeredGridLayoutManager != null) {
            spanCount = staggeredGridLayoutManager.getSpanCount();
        }
        if (Objects.requireNonNull(staggeredGridLayoutManager).getOrientation() == StaggeredGridLayoutManager.VERTICAL) {
            //横向
            if (position % spanCount == 0) {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
            } else if (position % spanCount == spanCount - 1) {
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            } else {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            }
            //垂直方向
            if (position < spanCount) {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            } else if (position >= itemCount - spanCount) {
                outRect.top = dpToPx(dpItemVertical) / 2;
            } else {
                outRect.top = dpToPx(dpItemVertical) / 2;
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            }
        } else {
            //横向
            if (position % spanCount == 0) {
                outRect.bottom = dpToPx(dpItemVertical) / 2;
            } else if (position % spanCount == spanCount - 1) {
                outRect.top = dpToPx(dpItemVertical) / 2;
            } else {
                outRect.right = dpToPx(dpItemVertical) / 2;
                outRect.left = dpToPx(dpItemVertical) / 2;
            }
            //垂直方向
            if (position < spanCount) {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
            } else if (position >= itemCount - spanCount) {
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            } else {
                outRect.right = dpToPx(dpItemHorizontal) / 2;
                outRect.left = dpToPx(dpItemHorizontal) / 2;
            }
        }
    }

    private int dpToPx(float dp) {
        return ConvertUtils.dp2px(dp);
    }

    public static class Builder {
        //Item垂直方向间距
        private float dpItemVertical;
        //Item水平方向间距
        private float dpItemHorizontal;

        private float left = -1, top = -1, right = -1, bottom = -1;

        private OuterDistanceType type;

        public Builder setVertical(float vertical) {
            this.dpItemVertical = vertical;
            return this;
        }

        public Builder setHorizontal(float horizontal) {
            this.dpItemHorizontal = horizontal;
            return this;
        }

        public Builder setLeft(float left) {
            this.left = left;
            return this;
        }

        public Builder setTop(float top) {
            this.top = top;
            return this;
        }

        public Builder setRight(float right) {
            this.right = right;
            return this;
        }

        public Builder setBottom(float bottom) {
            this.bottom = bottom;
            return this;
        }

        public Builder setOuterDistanceType(OuterDistanceType type) {
            this.type = type;
            return this;
        }

        public Builder init(float dp) {
            this.dpItemHorizontal = dp;
            this.dpItemVertical = dp;
            this.left = dp;
            this.top = dp;
            this.right = dp;
            this.bottom = dp;
            return this;
        }

        public CommonItemDecoration build() {
            CommonItemDecoration commonItemDecoration = new CommonItemDecoration();
            commonItemDecoration.setDpItemVertical(dpItemVertical);
            commonItemDecoration.setDpItemHorizontal(dpItemHorizontal);
            if (left >= 0) {
                commonItemDecoration.setLeft(left);
            }
            if (top >= 0) {
                commonItemDecoration.setTop(top);
            }
            if (right >= 0) {
                commonItemDecoration.setRight(right);
            }
            if (bottom >= 0) {
                commonItemDecoration.setBottom(bottom);
            }
            if (type != null) {
                commonItemDecoration.setType(type);
            }
            return commonItemDecoration;
        }

    }
}
